package com.openlogic.common.logic.func.aviator;

import java.util.Map;

import com.googlecode.aviator.runtime.function.AbstractVariadicFunction;
import com.googlecode.aviator.runtime.type.AviatorObject;
import com.googlecode.aviator.runtime.type.AviatorRuntimeJavaType;

/**
 * @ClassName: MedianFunc
 * @Description: 中位数自定义函数
 * @author weiyongpeng
 * @date 2024年12月27日 上午9:27:28
 */
public class MedianFunc extends AbstractVariadicFunction {

	private static final long serialVersionUID = -7377110880312266008L;

	@Override
	public String getName() {
		return "cus_statis.median";
	}

	@Override
	public AviatorObject variadicCall(Map<String, Object> env, AviatorObject... args) {
		int[] nums = new int[args.length];
//		double[] x = new double[args.length];
		for (int i = 0; i < args.length; i++) {
			Object value = args[i].getValue(env);
			if (value instanceof Long) {
				nums[i] = (Integer.parseInt(String.valueOf((Long) value)));
			} else if (value instanceof Double) {
				nums[i] = Integer.parseInt(String.valueOf(value));
			} else if (value instanceof Integer) {
				nums[i] = Integer.parseInt(String.valueOf((Integer) value));
			} else {
				nums[i] = Integer.parseInt(String.valueOf(value));
			}
		}
		if (nums.length == 0)
			return AviatorRuntimeJavaType.valueOf(0);
		int start = 0;
		int end = nums.length - 1;
		int index = partition(nums, start, end);
		if (nums.length % 2 == 0) {
			while (index != nums.length / 2 - 1) {
				if (index > nums.length / 2 - 1) {
					index = partition(nums, start, index - 1);
				} else {
					index = partition(nums, index + 1, end);
				}
			}
		} else {
			while (index != nums.length / 2) {
				if (index > nums.length / 2) {
					index = partition(nums, start, index - 1);
				} else {
					index = partition(nums, index + 1, end);
				}
			}
		}
		return AviatorRuntimeJavaType.valueOf(nums[index]);
	}

	private static int partition(int nums[], int start, int end) {
		int left = start;
		int right = end;
		int pivot = nums[left];
		while (left < right) {
			while (left < right && nums[right] >= pivot) {
				right--;
			}
			if (left < right) {
				nums[left] = nums[right];
				left++;
			}
			while (left < right && nums[left] <= pivot) {
				left++;
			}
			if (left < right) {
				nums[right] = nums[left];
				right--;
			}
		}
		nums[left] = pivot;
		return left;
	}

}
